/*
 * AVRGCC1_interrupt.c
 *
 * Created: 2011-11-28 10:22:20
 *  Author: ztx
 */ 

#include <avr/io.h>
#include <avr/interrupt.h>
#include <math.h>
#include <util/delay.h>
#include <inttypes.h>
#include <avr/sfr_defs.h>
#include <stdlib.h>

#define button_sensor_port PORTB
#define button_sensor_pin PINB
#define button_sensor_ddr DDRB
#define sensorpinnum 0		// define pin number

#define sensorpulsetime 10	//time to pulse sensor for
#define distthresh 1200		//distance threshold to be considered hand is there
#define idlereadtime 100	//defines the time between sensor reads when no hand is detected

#define nmos_control_port PORTC
#define nmos_control_ddr DDRC

#define dip_button_LED_port PORTD
#define dip_button_LED_pin PIND
#define dip_button_LED_ddr DDRD

#define SET_1(a,b) (a) |= (b)
#define CLE_0(a,b) (a) &= ~(b)

#define actuatorontime 100	//the amount of time the actuator is on

int diff_level;
int led_delay;
void int_init(void);
void port_init(void);
int readsensor(void);


void int_init(void)
{
	cli();
	PCICR |= (1<< PCIE0)|(1<<PCIE2);   // any change in PCINT7..0 and PCINT23..16 will cause an interrupt
	PCMSK0 |= (1<<PCINT7);             //pb7
	PCMSK2 |= (1<<PCINT23)|(1<<PCINT22)|(1<<PCINT21);        //pd5,6,7
	sei();
	
}

void port_init(void)
{
   	dip_button_LED_port = dip_button_LED_port & 0xE0;    //set led output 0    dip_button_LED=xxx0_0000
	dip_button_LED_ddr = dip_button_LED_ddr | 0x1F;    //set led output direction 
	dip_button_LED_ddr = dip_button_LED_ddr & 0x1F;    // set dip button input direction, now dip_button_LED_ddr=0001_1111
	
    nmos_control_port = 0x00;     // set nmos output 0    nmso_control_port=xx00_xxxx
	nmos_control_ddr = 0xFF;        // set nmos output direction xx11_xxxx
	//nmos_control_port=nmos_control_port | 0xF7;       //set PC3 which is the actuator pin low(close the actuator) xx00_0xxx
	//nmos_control_ddr=nmos_control_ddr |0x08;          //set PC3 output direction XX11_1XXX
	
	button_sensor_ddr = button_sensor_ddr & 0x7F;   // set pb7 input direction
	                                                 //need initiate sensor!!!!!!!!!
}



ISR (PCINT0_vect)
{
		
	if (diff_level==0)
	{
		diff_level=1;				// Level 2
		nmos_control_port = CLE_0(nmos_control_port, 0x10);
		nmos_control_port = SET_1(nmos_control_port, 0x20);
		dip_button_LED_port = CLE_0(dip_button_LED_port, 0x01);
		dip_button_LED_port = SET_1(dip_button_LED_port, 0x02);
	
	}
		
	else if (diff_level==1)
	{
		diff_level=2;
	}

	else if (diff_level==2)
	{
		diff_level=3;				// Level 3
		nmos_control_port = CLE_0(nmos_control_port, 0x20);
		nmos_control_port = SET_1(nmos_control_port, 0x10);
		dip_button_LED_port = CLE_0(dip_button_LED_port, 0x02);
		dip_button_LED_port = SET_1(dip_button_LED_port, 0x04);
		
	}
		
	else if (diff_level==3)
	{
		diff_level=4;
	}
		
	else if (diff_level==4)
	{
		diff_level=5;				// Level 4
		nmos_control_port = CLE_0(nmos_control_port, 0x30);
		dip_button_LED_port = CLE_0(dip_button_LED_port, 0x04);
		dip_button_LED_port = SET_1(dip_button_LED_port, 0x08);
	}
		
	else if (diff_level==5)
	{
		diff_level=6;
	}
		
	else if (diff_level==6)       
	{
		diff_level=7;				// Level 1
		nmos_control_port = SET_1(nmos_control_port, 0x30);
		dip_button_LED_port = CLE_0(dip_button_LED_port, 0x08);
		dip_button_LED_port = SET_1(dip_button_LED_port, 0x01);    //dip_button_LED_port=xxxx0_0001
			
	}
		
	else if (diff_level==7)
	{
		diff_level=0;
	}
		
}


int readsensor(void)	// read sensor function
{
	int count = 0;	// count timer variable
	int dist = 0;	// distance value
	button_sensor_port= button_sensor_port & ~(1<<sensorpinnum);	//ensure output is low by clearing port pin
	button_sensor_ddr = button_sensor_ddr | (1<<sensorpinnum);		// set direction to output
	button_sensor_port = button_sensor_port | (1<<sensorpinnum);	// drive output high
	_delay_ms(0.005);
	button_sensor_port= button_sensor_port & 0b11111110;	// set sensor pin low
	button_sensor_ddr = button_sensor_ddr & 0b11111110;		// and then make sensor pin an input
	count=0;
	dist=0;
	do
	{
		count = button_sensor_pin;								// hang out until first clock of returning pulse
		count = button_sensor_pin & (1<<sensorpinnum);			// clear all bits except sensor pin bit
		
	} while ((count != ((1<<sensorpinnum)|(dist>0xf0))));		// while senor pin is low 
	
	count = 0;
	dist=0;
	do 
	{
		dist = dist + 1;						// increment count
		count = button_sensor_pin & (1<<sensorpinnum);	//clear all bits except for sensor pin bit
	} while (count == (1<<sensorpinnum));		// while sensor is high
	
	return(dist);
			
}


int main(void)
{
	//_delay_ms(1000);
	int dist;		//distance value
	int randseed;	//random seed value
	int count = 0;
	int delaytime = 0;
	int count2 = 0;
	
		
	port_init();
	int_init();
	
	diff_level=0;				// Level 1
	nmos_control_port = SET_1(nmos_control_port, 0x30);
	dip_button_LED_port = CLE_0(dip_button_LED_port, 0x08);
	dip_button_LED_port = SET_1(dip_button_LED_port, 0x01);    //dip_button_LED_port=xxxx0_0001

	
	randseed = readsensor();
	srand(randseed);			// seed random with sensor reading
    _delay_ms(5);
	while(1)
    {   
		dist = readsensor();
		if (dist > distthresh)		// if no hand is detected
			{
				_delay_ms(5);
			}
		else							//otherwise
			{
				count=0;
				count2=0;
				delaytime = rand();	// get random value	//should be random value changed for debuging
				do 
				{
				count2=0;
				do 
				{
					count2++;
				} 
				while (count2<100);
				
				count++;
				} while (count<delaytime);
				
				//dist = readsensor();
				//if (dist < distthresh)	// if hand is still there
				
					//{
						dist = readsensor();
						if (dist < distthresh)
						{

						
						dip_button_LED_port = SET_1(dip_button_LED_port, 0x10);
						
						switch (diff_level)
						{
							case 0:
								_delay_ms(600);
								break;
							
							case 2:
								_delay_ms(400);
								break;
								
							case 4:
								_delay_ms(250);
								break;
								
							case 6:
								_delay_ms(125);
								break;

						}
						
						dip_button_LED_port = CLE_0(dip_button_LED_port, 0x10);
						
							
						//nmos_control_port =nmos_control_port | 0x08;        // turn actuator on xx00_0xxx|0000_1000=xx00_1xxx, pc3 on
						nmos_control_port = SET_1(nmos_control_port, 0x08);
						_delay_ms(500);
				
						//nmos_control_port =nmos_control_port & 0xF7;        //  turn actuator off xx00_1xxx&1111_0111=xx00_0xxx	
						nmos_control_port = CLE_0(nmos_control_port, 0x08);
						
						_delay_ms(1000);
						
						}	
						
						_delay_ms(5);						
					//}					
			}	// and then go back and read sensor again 
    
		}	
}
   
